/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package control;

import java.io.IOException;
import java.util.Timer;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
import midlet.GameDesign;
import model.Warrior;


public class PacWarriorApp extends GameCanvas implements Runnable{

    private static final int MIN_BUFFER = 20;
    private static final int VELOCIDADE = 3;
    private Timer tempo;
    private int delay = 30;
    private byte ultimaDirecao = -1;
    private boolean rodando;
    private int viewPortX = 100;
    private int viewPortY = 100;
    private LayerManager lm;
    private AnimacaoSprite animacaoSriteWarrior;
    private AnimacaoSprite animacaoSriteMonster1;
    private AnimacaoSprite animacaoSriteMonster2;
    private AnimacaoSprite animacaoSriteArmadilhaH;
    private AnimacaoSprite animacaoSriteArmadilhaV;


    private Warrior warrior;

    private GameDesign gameDesign;
    private Sprite spriteWarrior;
    private Sprite spriteMonster1;
    private Sprite spriteMonster2;
    private Sprite spriteMonster3;
    private Sprite spriteArmadilhaH;
    private Sprite spriteArmadilhaV;
    private TiledLayer tlAmbientes;
    private TiledLayer tlCaminho;
    private TiledLayer tlGramado;
    private TiledLayer tlLago1;
    private TiledLayer tlLago2;
    private TiledLayer tlTree;
    private TiledLayer tlArmadilha;
    private AnimacaoTile animacaoAgua;
    private AnimacaoTile animacaoArmadilhaH;
    private AnimacaoTile animacaoArmadilhaV;

    public PacWarriorApp(){
        super(true);
        try {
            this.setFullScreenMode(true);
            this.init();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void init() throws IOException{
        this.tempo = new Timer();
        this.gameDesign = new GameDesign();

        this.spriteWarrior = this.gameDesign.getWarrior();
        this.animacaoSriteWarrior = new AnimacaoSprite(this.spriteWarrior, false);
        this.spriteWarrior.defineReferencePixel(12, 12);
        this.tempo.scheduleAtFixedRate(this.animacaoSriteWarrior, 0, gameDesign.warriorDownSeqDelay);

        this.tlAmbientes = this.gameDesign.getAmbientes();
        this.tlCaminho = this.gameDesign.getCaminho();
        this.tlGramado = this.gameDesign.getGramado();
        this.tlLago1 = this.gameDesign.getLago1();
        this.tlLago2 = this.gameDesign.getLago2();
        this.tlTree = this.gameDesign.getTree();
        this.tlArmadilha = this.gameDesign.getArmadilhas();


//        this.warrior = new Warrior(this.gameDesign, this.spriteWarrior);

        this.spriteArmadilhaH = this.gameDesign.getArmadilhaH();
        this.animacaoSriteArmadilhaH = new AnimacaoSprite(this.spriteArmadilhaH, false);
        this.spriteArmadilhaH.defineReferencePixel(12, 12);
        this.tempo.scheduleAtFixedRate(this.animacaoSriteArmadilhaH, 0, gameDesign.armadilhaHseq001Delay);

        this.spriteArmadilhaV = this.gameDesign.getArmadilhaV();
        this.animacaoSriteArmadilhaV = new AnimacaoSprite(this.spriteArmadilhaV, false);
        this.spriteArmadilhaV.defineReferencePixel(12, 12);
        this.tempo.scheduleAtFixedRate(this.animacaoSriteArmadilhaV, 0, gameDesign.armadilhaVseq001Delay);

        this.animacaoAgua = new AnimacaoTile(gameDesign.getLago1(), gameDesign.matinhoAguaLago1, gameDesign.matinhoAguaseq001, true);
        this.tempo.scheduleAtFixedRate(this.animacaoAgua, 0, gameDesign.matinhoAguaseq001Delay);

        this.animacaoArmadilhaH = new AnimacaoTile(gameDesign.getArmadilhas(), gameDesign.trapHorizontalArmadilhas, gameDesign.trapHorizontalseq001, true);
        this.tempo.scheduleAtFixedRate(this.animacaoArmadilhaH, 0, gameDesign.trapHorizontalseq001Delay);

        this.animacaoArmadilhaV = new AnimacaoTile(gameDesign.getArmadilhas(), gameDesign.trapVerticalArmadilhas, gameDesign.trapVerticalseq001, true);
        this.tempo.scheduleAtFixedRate(this.animacaoArmadilhaV, 0, gameDesign.trapVerticalseq001Delay);

        this.lm = new LayerManager();
        gameDesign.updateLayerManagerForFloresta(lm);
        this.lm.setViewWindow(this.viewPortX, this.viewPortY, 240, 340);

        this.spriteMonster1 = this.gameDesign.getMonster1();
        this.spriteMonster1.defineReferencePixel(12, 12);
        this.animacaoSriteMonster1 = new AnimacaoSprite(this.spriteMonster1, false);

        this.spriteMonster2 = this.gameDesign.getMonster2();
        this.spriteMonster2.defineReferencePixel(12, 12);
        this.animacaoSriteMonster2 = new AnimacaoSprite(this.spriteMonster2, false);
    }

    public void start(){
        rodando = true;
        Thread t = new Thread(this);
        t.start();
    }

    public void stop(){
        rodando = false;
    }

    public void run() {
        Graphics g = getGraphics();

        while(!this.rodando){

            int keyState = getKeyStates();

            //if user is pressing the left button
            if ((keyState & LEFT_PRESSED) != 0) {
                //if the previous direction was other than left set the sequence
                //correct sequence & transform needed for walking to the left
                if (this.ultimaDirecao != LEFT) {
                    this.ultimaDirecao = LEFT;
                    this.spriteWarrior.setFrameSequence(gameDesign.warriorLeftSeq);
                    continue;
                }
                //assign the sequence playback direction
                this.animacaoSriteWarrior.adiantar();
                //move the sprite to the left
                this.spriteWarrior.move(-VELOCIDADE, 0);
                //if moving the sprite generates a collision return sprite back
                //to its original position
                if (this.checarColisoes(this.spriteWarrior)) {
                    this.spriteWarrior.move(VELOCIDADE, 0);
                    continue;
                }
                //attempt to adjust the viewport to keep the sprite on the screen
                this.ajustarViewport(this.viewPortX - VELOCIDADE, this.viewPortY);
            } else if ((keyState & RIGHT_PRESSED) != 0) {
                if (this.ultimaDirecao != RIGHT) {
                    this.ultimaDirecao = RIGHT;
                    this.spriteWarrior.setFrameSequence(gameDesign.warriorRightSeq);
                    this.spriteWarrior.setTransform(Sprite.TRANS_NONE);
                    continue;
                }
                this.animacaoSriteWarrior.adiantar();
                this.spriteWarrior.move(VELOCIDADE, 0);
                if (this.checarColisoes(this.spriteWarrior)) {
                    this.spriteWarrior.move(-VELOCIDADE, 0);
                    continue;
                }
                this.ajustarViewport(this.viewPortX + VELOCIDADE, this.viewPortY);
            } else if ((keyState & UP_PRESSED) != 0) {
                if (this.ultimaDirecao != UP) {
                    this.ultimaDirecao = UP;
                    this.spriteWarrior.setFrameSequence(gameDesign.warriorUpSeq);
                    this.spriteWarrior.setTransform(Sprite.TRANS_NONE);
                    continue;
                }
                this.animacaoSriteWarrior.adiantar();
                this.spriteWarrior.move(0, -VELOCIDADE);
                if (this.checarColisoes(this.spriteWarrior)) {
                    this.spriteWarrior.move(0, VELOCIDADE);
                    continue;
                }
                this.ajustarViewport(this.viewPortX, this.viewPortY - VELOCIDADE);
            } else if ((keyState & DOWN_PRESSED) != 0) {
                if (this.ultimaDirecao != DOWN) {
                    this.ultimaDirecao = DOWN;
                    this.spriteWarrior.setFrameSequence(gameDesign.warriorDownSeq);
                    this.spriteWarrior.setTransform(Sprite.TRANS_NONE);
                    continue;
                }
                this.animacaoSriteWarrior.adiantar();
                this.spriteWarrior.move(0, VELOCIDADE);
                if (this.checarColisoes(this.spriteWarrior)) {
                    this.spriteWarrior.move(0, -VELOCIDADE);
                    continue;
                }
                this.ajustarViewport(this.viewPortX, this.viewPortY + VELOCIDADE);
            } else {
                this.animacaoSriteWarrior.setMovendo(false);
            }


            this.lm.paint(g, 0, 0);
            flushGraphics(0, 0, this.getWidth(), this.getHeight());

            try {
                Thread.sleep(20);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        
    }

    public boolean checarColisoes(Sprite sprite){
    return sprite.collidesWith(
            sprite == this.spriteWarrior ? this.spriteMonster1 : this.spriteMonster2, true)
            || sprite.collidesWith(this.tlAmbientes, true)
            || sprite.collidesWith(this.tlGramado, true)
            || sprite.collidesWith(this.tlLago1, true)
            || sprite.collidesWith(this.tlLago2, true)
            || sprite.getX() < 0 || sprite.getY() < 0
            || sprite.getX() > (this.tlCaminho.getWidth() - sprite.getWidth())
            || sprite.getY() > (this.tlCaminho.getHeight() - sprite.getHeight())
            ;
    }

    public boolean checarArmadilhaColisao(Sprite sprite){
        boolean colidido = sprite.collidesWith(this.tlArmadilha, true);

        if(colidido){
        }
        return false;
    }

    private void ajustarViewport(int x, int y) {

        int sx = this.spriteWarrior.getX();
        int sy = this.spriteWarrior.getY();

        int xmin = this.viewPortX + MIN_BUFFER;
        int xmax = this.viewPortX + this.getWidth() - this.spriteWarrior.getWidth() - MIN_BUFFER;
        int ymin = this.viewPortY + MIN_BUFFER;
        int ymax = this.viewPortY + this.getHeight() - this.spriteWarrior.getHeight() - MIN_BUFFER;

        if (sx >= xmin && sx <= xmax && sy >= ymin && sy <= ymax) {
            return;
        }

        if (this.ultimaDirecao == LEFT && sx >= xmin) {
            return;
        }
        if (this.ultimaDirecao == RIGHT && sx <= xmax) {
            return;
        }
        if (this.ultimaDirecao == UP && sy >= ymin) {
            return;
        }
        if (this.ultimaDirecao == DOWN && sy <= ymax) {
            return;
        }

        if (x < this.tlGramado.getX()) {
            this.viewPortX = this.tlGramado.getX();
        } else if (x > this.tlGramado.getX() + this.tlGramado.getWidth() - this.getWidth()) {
            this.viewPortX = this.tlGramado.getX() + this.tlGramado.getWidth() - this.getWidth();
        } else {
            this.viewPortX = x;
        }

        //only adjust y to values that ensure the base tiled layer remains visible
        //and no white space is shown
        if (y < this.tlGramado.getY()) {
            this.viewPortY = this.tlGramado.getY();
        } else if (y > this.tlGramado.getY() + this.tlGramado.getHeight() - this.getHeight()) {
            this.viewPortY = this.tlGramado.getY() + this.tlGramado.getHeight() - this.getHeight();
        } else {
            this.viewPortY = y;
        }

        //adjust the viewport
        this.lm.setViewWindow(this.viewPortX, this.viewPortY, this.getWidth(), this.getHeight());
    }

    public void criarPontos(){

    }

    public void methodWarriorWall(int keyState){
        
    }
}
